import { isObject, cloneDeep } from 'lodash';
import Model from '../toast';

const $logout = () => {};

const getErr = err => {
  let message = '';
  if (typeof err == 'string') {
    message = err;
    err = { code: 500 };
  } else if (err instanceof Error) {
    return err;
  } else if (typeof err == 'object') {
    message = err.message;
  } else {
    err = {};
    message = '错误';
  }
  return {
    ...err,
    stack: '',
    message
  };
};

/**
 * 验证响应结果，并返回
 * @param {*} onfulfilled
 * @returns
 */
export const done = function (onfulfilled) {
  return this.then(res => {
    if (res == null || (isObject(res) && typeof res.code !== 'number')) return onfulfilled ? onfulfilled(res) : res;

    if (res.code != 0) {
      return Promise.reject(res);
    }
    if (typeof res.count === 'number') {
      Object.defineProperty(res.data, 'count', {
        enumerable: false,
        get: function () {
          return res.count;
        }
      });
    }
    return onfulfilled ? onfulfilled(res.data) : res.data;
  });
};

/**
 * 弹出错误提醒
 * @returns
 */
export const error = function (msg) {
  return this.catch(err => {
    err = getErr(err);

    if (err.isShow) {
      return Promise.reject(err);
    }
    err.isShow = true;
    if ((err.code ?? 1) == 1) {
      Model.error('系统错误，请稍后再试！');
      console.error(err);
      return Promise.reject(err);
    }
    Model.error(msg || err.message || '系统错误，请稍后再试！');
    if (3001 == err.code) {
      $logout();
    }
    return Promise.reject(err);
  });
};

export const toast = function (msg, noClog) {
  return this.success(msg, noClog).error();
};

/**
 * 弹出成功提醒
 * @returns
 */
export const success = function (msg, noClog) {
  return this.then(async data => {
    await Model.success(msg, noClog);
    return data;
  });
};

/**
 * 睡
 * @param {*} timeout
 * @returns
 */
export const sleep = function (timeout) {
  return this.then(data => {
    return new Promise(res => setTimeout(() => res(data), timeout));
  });
};

export const _sleep = function (timeout, data) {
  return new Promise(res => setTimeout(() => res(data), timeout));
};

const __cacheData = {};

/** 单线缓存 */
export const _singleCache = function (key, call, timeout = 300, clear = false) {
  if (clear) {
    __cacheData[key] = null;
  }
  const result = __cacheData[key];

  if (!result || result.timeout < Date.now()) {
    let __callfun;
    __cacheData[key] = () => {
      return new Promise(resolve => {
        __callfun = resolve;
      });
    };
    return call().then(r => {
      __callfun?.call(null, r);
      __cacheData[key] = {
        timeout: Date.now() + timeout * 1000,
        data: r
      };
      return r;
    });
  }
  if (typeof result == 'function') {
    return result();
  }
  return Promise.resolve(cloneDeep(result.data));
};
